package java核心及工具类;
/**
 * 老紫竹JAVA提高教程 - System.arraycopy方法的使用。

 * 

 * 从指定源数组中复制一个数组，复制从指定的位置开始，

 * 到目标数组的指定位置结束
 *
 * @author 老紫竹的家(java2000.net,laozizhu.com)
 *
 */
public class LessionSystemArraycopy {
  public static void main(String[] args) {
    // 此方位为native方法。
    // public static native void arraycopy(
    // Object src, int srcPos, Object dest,
    // int destPos, int length);
    // 初始化
    int[] ids = { 1, 2, 3, 4, 5 };
    System.out.println(Arrays.toString(ids)); // [1, 2, 3, 4, 5]
    // 测试自我复制
    // 把从索引0开始的2个数字复制到索引为3的位置上
    System.arraycopy(ids, 0, ids, 3, 2);
    System.out.println(Arrays.toString(ids)); // [1, 2, 3, 1, 2]
    // 测试复制到别的数组上
    // 将数据的索引1开始的3个数据复制到目标的索引为0的位置上
    int[] ids2 = new int[6];
    System.arraycopy(ids, 1, ids2, 0, 3);
    System.out.println(Arrays.toString(ids2)); // [2, 3, 1, 0, 0, 0]
    // 此功能要求
    // 源的起始位置+长度不能超过末尾
    // 目标起始位置+长度不能超过末尾
    // 且所有的参数不能为负数
    try {
      System.arraycopy(ids, 0, ids2, 0, ids.length + 1);
    } catch (IndexOutOfBoundsException ex) {
      // 发生越界异常，数据不会改变
      System.out.println("拷贝发生异常：数据越界。");
    }
    System.out.println(Arrays.toString(ids2)); // [2, 3, 1, 0, 0, 0]
    // 如果是类型转换问题
    Object[] o1 = { 1, 2, 3, 4.5, 6.7 };
    Integer[] o2 = new Integer[5];
    System.out.println(Arrays.toString(o2)); // [null, null, null, null, null]
    try {
      System.arraycopy(o1, 0, o2, 0, o1.length);
    } catch (ArrayStoreException ex) {
      // 发生存储转换，部分成功的数据会被复制过去
      System.out.println("拷贝发生异常：数据转换错误，无法存储。");
    }
    // 从结果看，前面3个可以复制的数据已经被存储了。剩下的则没有
    System.out.println(Arrays.toString(o2)); // [1, 2, 3, null, null]
  }
}


《currentTimeMillis——返回毫秒数》
这个就不举例了，currentTimeMillis方法和Date类中getTime方法完全是一样的，如果只是需要毫秒数，这样的调用也是很方便的。但是需要注意的
是currentTimeMillis并不是直接拿到了getTime的结果，currentTimeMillis是一个本地方法，返回的是操作系统的时间，由于有的操作系统时间
的最小精确度是10毫秒所以这个方法可能会导致一些偏差。
Java System.currentTimeMillis() 返回毫秒为单位的当前时间
System.currentTimeMillis() 返回当前的计算机时间，时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。

语法
public static long currentTimeMillis()

获得的将是一个长整型的数字，该数字就是以差值表达的当前时间。使用该方法获得的时间不够直观，但是却很方便时间的计算。

例子
计算程序运行需要的时间

long start = System. currentTimeMillis();
for(int i = 0;i < 100000000;i++)
{ 
    int a = 0; 
} 
long end = System. currentTimeMillis(); 
long time = end – start; 
这里变量time的值就代表该代码中间的for循环执行需要的毫秒数，使用这种方式可以测试不同算法的程序的执行效率高低，也可以用于后期线程控制时的精确延时实现。


《getProperty——获取系统属性》
我们通过调用这个方法，在参数中输入键的字符串获取系统的属性。

   键                                               相关值的描述
java.version                                    Java 运行时环境版本
java.vendor                                     Java运行时环境供应商
java.vendor.url                                 Java 供应商的 URL
java.home                                       Java 安装目录
java.vm.specification.version                   Java 虚拟机规范版本
java.vm.specification.vendor                    Java 虚拟机规范供应商
java.vm.specification.name                      Java 虚拟机规范名称
java.vm.version                                 Java 虚拟机实现版本
java.vm.vendor                                  Java 虚拟机实现供应商
java.vm.name                                    Java 虚拟机实现名称
java.specification.version                      Java 运行时环境规范版本
java.specification.vendor                       Java 运行时环境规范供应商
java.specification.name                         Java 运行时环境规范名称
java.class.version                              Java 类格式版本号
java.class.path                                 Java 类路径
java.library.path                               加载库时搜索的路径列表
java.io.tmpdir                                  默认的临时文件路径
java.compiler                                   要使用的 JIT 编译器的名称
java.ext.dirs                                   一个或多个扩展目录的路径
os.name                                         操作系统的名称
os.arch                                         操作系统的架构
os.version                                      操作系统的版本
file.separator                                  文件分隔符（在 UNIX 系统中是“/”）
path.separator                                  路径分隔符（在 UNIX 系统中是“:”）
line.separator                                  行分隔符（在 UNIX 系统中是“/n”）
user.name                                       用户的账户名称
user.home                                       用户的主目录
user.dir                                        用户的当前工作目录
在我们操作文件的时候很可能需要使用到我们的当前工作目录，可以用这个方法来获得。

public static void main(String[] args) {  
      String dirPath = System.getProperty("user.dir");  
      System.out.println(dirPath);  
      //输出工作目录  D:\Workspaces\MyEclipse 10\Algorithms（这是我的目录，每个人都不同）  
  }  

假如我想知道我当前操作系统的系统名和版本号，可以如下写：

public static void main(String argv[]) {
    String osName = System.getProperty("os.name");
    String osVer = System.getProperty("os.version");
    System.out.println(osName + " v" + osVer);
}

上面的表中就不再举例了，比较常用的是后几个key。

《gc——运行垃圾回收器》
调用 gc 方法暗示着 Java 虚拟机做了一些努力来回收未用对象或失去了所有引用的对象，以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回
时，虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。

public static void main(String[] args) {  
  
      Date d = new Date();  
      d = null;  
  
      System.gc();  
      // 在调用这句gc方法时，上面已经失去了d引用的new Date()被回收  
  
  }  
实际上我们并不一定需要调用gc()方法，让编译器自己去做好了。如果调用gc方法，会在对象被回收之前调用finalize()方法，但是我们也知道finalize()方法不一定
会被调用。总之java在这回收方面做的远不如c和c++。我们可以规避有关回收方面的问题。当需要了解的时候最好专门的去看JVM回收机制的文章。

《exit——退出虚拟机》
exit(int)方法终止当前正在运行的 Java 虚拟机，参数解释为状态码。根据惯例，非 0 的状态码表示异常终止。 而且，该方法永远不会正常返回。 这是唯一一个能够退出
程序并不执行finally的情况。

public static void main(String[] args) {  
  
      try {  
          System.out.println("this is try");  
          System.exit(0);  
      } catch (Exception e) {  
          // TODO Auto-generated catch block  
          e.printStackTrace();  
      } finally {  
          System.out.println("this is finally");  
      }  
  
  }  
这段程序最后只会输出 this is try 这一句话，而不会输出 this is finally 。退出虚拟机会直接杀死整个程序，已经不是从代码的层面来终止程序了，所以finally不会执行。

例子
public static void main(String[] args)   
    {  
        //测试arraycopy方法,注意，目的空间必须提前分配  
        int[] src = {1,2,3,4,5,6,7,8,9};  
        System.out.println("System.arraycopy");  
        int[] dst = new int[src.length];  
        System.arraycopy(src, 0, dst, 0, src.length);  
        System.out.println("src = "+Arrays.toString(src));  
        System.out.println("dst = "+Arrays.toString(dst));  
        //同样是拷贝，Arrays.copyOf方法就不需要手动开辟空间  
        System.out.println("Arrays.copyOf");  
        int[] dst1 = Arrays.copyOf(src, src.length);  
        System.out.println("src = "+Arrays.toString(src));  
        System.out.println("dst1 = "+Arrays.toString(dst1));  
  
        //测试currentTimeMillis()  
        System.out.println("currentTimeMillis "+System.currentTimeMillis());  
        //测试nanoTime()，单独输出的结果没有仍和意义，此函数只能用来计算时间差  
        System.out.println("nanoTime "+System.nanoTime());  
        long dt=System.nanoTime();  
        dt = dt - System.nanoTime();  
        System.out.println("dt = "+dt);  
  
        //测试getenv(),注意遍历Map的用法,不是很理解  
        System.out.println("System.getenv");  
        Map<String,String> env = System.getenv();  
        Iterator it = env.entrySet().iterator();  
        while(it.hasNext())  
        {  
            Map.Entry a = (Map.Entry)it.next();  
            System.out.println("<"+a.getKey()+"> = <"+a.getValue()+">;");  
        }  
  
        //getProperties(),注意遍历Map的用法,不是很理解  
        System.out.println("System.getProperties");  
        Properties p = System.getProperties();  
        p.list(System.out);  
  
        System.out.println("Hello World!");  
    }






